<template>
  <h1>
    <div class="validate-input-container pb-3">
      <input class="form-control"
             :class="{'is-invalid':inputRef.error}"
             @blur="validateInput"
             :value="inputRef.val"
             @input="upDateValue"
             v-bind="$attrs"
      />
      <span v-if="inputRef.error" class="invalid-feedback" style="display: block">
        {{ inputRef.message }}
      </span>
    </div>
  </h1>
</template>

<script lang="ts">
import { defineComponent, PropType, reactive, onMounted } from 'vue'
import { emailReg } from '@/utils'
import { emitter } from './ValidateForm.vue'
interface RuleProp {
  type: 'required' | 'email';
  message?: string;
}

export type RulesProp = RuleProp[]
export default defineComponent({
  name: 'ValidateInput',
  // 禁用 Attribute 继承
  // 参考文档：https://v3.cn.vuejs.org/guide/component-attrs.html#%E7%A6%81%E7%94%A8-attribute-%E7%BB%A7%E6%89%BF
  inheritAttrs: false,
  props: {
    roles: Array as PropType<RulesProp>,
    modelValue: String // 父组件使用v-model传递过来这里接收
  },
  setup (props, context) {
    const inputRef = reactive({
      val: props.modelValue || '', // 将接收的值设置为默认值
      error: false,
      message: ''
    })

    onMounted(() => {
      emitter.emit('form-item-created', validateInput)
    })
    const upDateValue = (e: KeyboardEvent) => {
      const targetValue = (e.target as HTMLInputElement).value
      inputRef.val = targetValue
      context.emit('update:modeValue', targetValue) // 调用update:modeValue实现v-model的双向绑定
    }
    const validateInput = () => {
      if (props.roles) {
        const allPassed = props.roles.every(e => {
          let passed = true
          inputRef.message = e.message || ''
          switch (e.type) {
            case 'required':
              passed = inputRef.val.trim() !== ''
              break
            case 'email':
              passed = emailReg.test(inputRef.val)
              break
            default:
              break
          }
          return passed
        })
        inputRef.error = !allPassed
        return allPassed
      }
      return true
    }
    return {
      validateInput,
      inputRef,
      upDateValue
    }
  }
})
</script>

<style scoped>

</style>
